﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SCG.SolarVengeanceEngine;
using SCG.SolarVengeance.Scenarios;
using SCG.General;
using System.IO;
using SCG.WinForms;

namespace SCG.SolarVengeance
{
    public partial class BrainDuelPage : BasePage, IComparer<Brain>
    {
        //constructor
        public BrainDuelPage()
        {
            InitializeComponent();
        }

        //initialize
        public override void Initialize()
        {
            elastic.ForceResize();
        }

        //brain rankings received
        public void BrainRankingsRecieved(List<Brain> ratedBrains)
        {
            int rank = 1;
            ratedBrains.Sort(this);
            lvBrainRanking.Items.Clear();
            images.Images.Clear();
            foreach (Brain b in ratedBrains)
            {
                ListViewItem lvi = lvBrainRanking.Items.Add(rank + ".");
                rank++;
                lvi.SubItems.Add(b.BrainName);
                lvi.SubItems.Add(b.Rating.ToString("N0"));
                string fileName = "Images\\Brains\\" + b.GetType().Name + ".bmp";
                if (File.Exists(fileName))
                {
                    Image glyph = Bitmap.FromFile(fileName);
                    glyph = ImageUtils.ResizeBitmap(glyph, 60, 60, true);
                    images.Images.Add(glyph);
                    lvi.ImageIndex = images.Images.Count - 1;
                }
            }
        }

        //resizing
        private void lvBrainRanking_SizeChanged(object sender, EventArgs e)
        {
            colBrain.Width = lvBrainRanking.Width - System.Windows.Forms.SystemInformation.VerticalScrollBarWidth - 4 - colRank.Width - colRating.Width;
        }

        //return
        private bool _cancel = false;
        private void btnExit_Click(object sender, EventArgs e)
        {
            _cancel = true;
            MainForm.ShowPage(Pages.Lobby);
        }

        //brain duels!
        private void btnBegin_Click(object sender, EventArgs e)
        {
            _cancel = false;
            btnBegin.Visible = false;
            progDuels.Visible = true;
            lblStatus.Text = "";
            lblStatus.Visible = true;
            progDuels.Value = 0;
            int numBrains = MainForm.TitlePage.Brains.Count;
            int combinations = (numBrains * (numBrains - 1)) / 2;
            progDuels.Maximum = combinations;
            Tokenizer tok = new Tokenizer();
            try
            {
                txtResults.Text = "";
                List<string> matches = new List<string>();
                List<string> empty = new List<string>();
                foreach(Brain brain1 in MainForm.TitlePage.Brains)
                    foreach (Brain brain2 in MainForm.TitlePage.Brains)
                    {
                        if (brain1 == brain2)
                            continue;
                        MatchInfo match = new MatchInfo();
                        match.Player1 = brain1.BrainName;
                        match.Player2 = brain2.BrainName;
                        if (!matches.Contains(match.MatchCode))
                        {
                            matches.Add(match.MatchCode);
                            SVGame game = new SVGame(null);
                            Scenario scen = new UltimateBrainTester();
                            scen.BuildScenaio(game, MainForm.Confluxer, 2, 20, 100, null);
                            game.Players[0].Brain = MainForm.TitlePage.CloneBrain(brain1);
                            game.Players[1].Brain = MainForm.TitlePage.CloneBrain(brain2);
                            int impulsesSinceChange = 0;
                            while (!game.Victory)
                            {
                                if (_cancel)
                                {
                                    txtResults.Text += "Brain Duels cancelled." + Environment.NewLine;
                                    btnBegin.Visible = true;
                                    return;
                                }
                                List<string> orders = empty;
                                if (game.Impulse % 10 == 0)
                                    orders = game.Players[0].ExecuteBrain();
                                else if (game.Impulse % 10 == 1)
                                    orders = game.Players[1].ExecuteBrain();
                                game.ProcessImpulse(game.Impulse + 1, orders);
                                string status = brain1.BrainName + " (" + game.Players[0].NumStarSystems + ") " +
                                    brain2.BrainName + " (" + game.Players[1].NumStarSystems + ") Impulse: " + game.Impulse;
                                lblStatus.Text = status;
                                lblStatus.Refresh();

                                //detect stalemate
                                if (brain1.MatchInfo == game.Players[0].NumStarSystems && brain2.MatchInfo == game.Players[1].NumStarSystems)
                                    impulsesSinceChange++;
                                else
                                {
                                    impulsesSinceChange = 0;
                                    brain1.MatchInfo = game.Players[0].NumStarSystems;
                                    brain2.MatchInfo = game.Players[1].NumStarSystems;
                                }
                                if (impulsesSinceChange >= 1000)
                                    break;

                                Application.DoEvents();
                            }
                            string s;
                            if (game.Players[0].Victor)
                            {
                                s = brain1.BrainName + " defeated " + brain2.BrainName;
                                tok.AppendToken(brain1.BrainName);
                                tok.AppendToken(brain2.BrainName);
                            }
                            else if (game.Players[1].Victor)
                            {
                                s = brain2.BrainName + " defeated " + brain1.BrainName;
                                tok.AppendToken(brain2.BrainName);
                                tok.AppendToken(brain1.BrainName);
                            }
                            else
                                s = brain1.BrainName + " and " + brain2.BrainName + " ended in stalemate";
                            s += " in " + game.Impulse + " Impulses.";
                            txtResults.Text += s + Environment.NewLine;
                            txtResults.SelectionStart = txtResults.Text.Length;
                            txtResults.ScrollToCaret();
                            txtResults.Refresh();
                            progDuels.Value++;
                            progDuels.Refresh();
                        }
                    }

                //submit the results
                string results = tok.Result;
                MainForm.Prism.CustomCommand("SVBrainDuel", results);
                txtResults.Text += "Results submitted to PrismServer.";
                txtResults.SelectionStart = txtResults.Text.Length;
                txtResults.ScrollToCaret();

                btnBegin.Visible = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error conducting Brain Duels: " + ex.Message);
                btnBegin.Visible = true;
            }
        }

        //sort brains
        public int Compare(Brain x, Brain y)
        {
            return y.Rating.CompareTo(x.Rating);
        }
    }
}
